package com.tanzc.mp3player;

import com.tanzc.mp3player.filter.FilenameSuffixFilter;
import javazoom.jl.decoder.JavaLayerException;
import javazoom.jl.player.advanced.AdvancedPlayer;

import java.io.*;
import java.lang.management.ManagementFactory;
import java.lang.management.RuntimeMXBean;
import java.nio.file.FileSystemException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * <p> description: 简单的mp3音乐播放器
 * 无界面
 * 指定音乐目录，随机播放音乐
 * 没有暂停功能，没有音量调节功能->这个Player好像就没这东西
 * 无法调节音量，这个有点伤，因为它的声音太大了，系统声音都调到2了声音还是有点大
 * </p>
 *
 * @author tanzc
 * @date 11:25 2021/5/21
 **/
public class Mp3Player {

    private AdvancedPlayer player;

    final private String mp3Dir;

    final private FilenameFilter filter;

    Thread thread;

    public static void main(String[] args) {
        Mp3Player mp3Player = new Mp3Player(args.length == 0 ? "I:\\Musics" : args[0], "mp3");
        System.out.println("current process id: " + mp3Player.getProcessId());
        System.out.println("playing dir: " + mp3Player.mp3Dir);
        try {
            mp3Player.playMp3Rotate2(new File(mp3Player.mp3Dir));
        } catch (JavaLayerException | FileSystemException | FileNotFoundException e) {
            e.printStackTrace();
        }
    }

    public Mp3Player(String mp3Dir, String type) {
        this.mp3Dir = mp3Dir;
        this.filter = new FilenameSuffixFilter(type);
    }

    public String getMp3Dir() {
        return mp3Dir;
    }

    public int getProcessId() {
        RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
//        System.out.println(runtimeMxBean.getName());
        return Integer.parseInt(runtimeMxBean.getName().split("@")[0]);
    }

    /**
     * <p> Description: 停掉循环播放音乐的线程</p>
     **/
    public void stopMp3Rotate() {
        thread.interrupt();
        if(thread.isInterrupted()){
            thread.stop();
        }
    }

    /**
     * <p> Description: 由于playMp3Rotate2内有死循环，会导致调用线程阻塞，所以在本类中先使用线程调用，强行停止时风险较小</p>
     * @param mapDir mapDir
     **/
    public void playMp3Rotate(File mapDir) {
        thread = new Thread(() -> {
            try {
                playMp3Rotate2(mapDir);
            } catch (JavaLayerException | FileSystemException | FileNotFoundException e) {
                e.printStackTrace();
            }
        });
        thread.start();
    }

    /**
     * <p> Description: 接收一个mp3音乐目录，死循环播放</p>
     * @param mp3Dir mp3Dir
     **/
    public void playMp3Rotate2(File mp3Dir) throws JavaLayerException, FileSystemException, FileNotFoundException {
        // 初始化获取音乐列表
        List<String> mp3List = getMp3List(mp3Dir), mp3ListTemp;
        String currentMp3 = null;
        int size = mp3List.size(), index, randomSize = size - size / 3;

        while (true) {
            index = (int) Math.floor((Math.random() * randomSize));
            currentMp3 = mp3List.get(index);
            play(new File(mp3Dir, currentMp3));

            // 每播完一首歌，检查音乐数量是否变化
            mp3ListTemp = getMp3List(mp3Dir);
            if (size != mp3ListTemp.size()) {
                mp3List = mp3ListTemp;
                size = mp3List.size();
                // 设置随机排除音乐数，将部分音乐排除在随机池外，避免过快播放相同音乐
                randomSize = size - size / 4;
            } else {
                // 刚播放的歌曲放到随机列表尾
                mp3List.remove(currentMp3);
                mp3List.add(currentMp3);
            }
        }
    }

    public void play(File mp3) throws FileNotFoundException, JavaLayerException {
        initPlayer(mp3);
        player.play();
    }

    public void stop() {
        player.close();
    }

    public void initPlayer(File mp3) throws FileNotFoundException, JavaLayerException {
        FileInputStream inputStream = new FileInputStream(mp3);
        BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);
        player = new AdvancedPlayer(bufferedInputStream);
    }

    public List<String> getMp3List(File musicDir) throws FileSystemException, FileNotFoundException {
        if (!musicDir.isDirectory()) {
            throw new FileSystemException(musicDir + "is not a directory.");
        }
        String[] mp3mp3 = musicDir.list(filter);
        if (mp3mp3 == null || mp3mp3.length == 0) {
            throw new FileNotFoundException("no mp3 file in " + musicDir + ".");
        }
        List<String> mp3List = new ArrayList<>(Arrays.asList(mp3mp3));
        return mp3List;
    }
}
